/*******************************************************************************
*	                           bsp ram clear.c
*******************************************************************************/
#include "bsp.h"
#include "bsp_spi_nor.h"
#include "pincfg.h"
#include "nor_cmd.h"

#define NOR_SPI SPI4
#define ISR_IRQn SPI4_IRQn

uint8_t b_io_q_mode = 0;

/*****************************************************************************
* @brief   hal init.
*
* @param   none
*
* @return  none
*
* @ Pass/ Fail criteria: none
*****************************************************************************/
void nor_spi_init(void)
{
	intx_alloc();

	nor_ss.en();

	intx_disable();

	intx_enable();

	NOR_SPI->CR1 |= SPI_CR1_SPE;

	b_io_q_mode = 0;
}

/*****************************************************************************
* @brief   cs ctr.
*
* @param   none
*
* @return  none
*
* @ Pass/ Fail criteria: none
*****************************************************************************/
void nor_spi_cs(uint8_t st)
{
	if (st)
	{
		nor_ss.en();
		bsp_delay_us(1);
		NOP40();
	}
	else
	{
		nor_ss.dis();
		bsp_delay_us(1);
		NOP40();
	}
}

/*****************************************************************************
* @brief   spi mode select.
*****************************************************************************/
void nor_hal_mode_spi(void){b_io_q_mode = 0;};
void nor_hal_mode_qpi_out(void){b_io_q_mode = 1;};
void nor_hal_mode_qpi_in(void){b_io_q_mode = 1;};
/*****************************************************************************
* @brief   spi speed.
*****************************************************************************/
void nor_spi_high_speed(void)
{
}

/*****************************************************************************
* @brief   spi speed.
*****************************************************************************/
void nor_spi_low_speed(void)
{
}

/*****************************************************************************
* @brief   spi delay.
*****************************************************************************/
#define spi_read_delay() NOP8()
#define is_spi_rx_ready(spix) ((spix->SR & SPI_SR_RXNE) != 0)
#define spi_rx_reset(spix)               \
	while (is_spi_rx_ready(spix))        \
	{                                    \
		volatile uint32_t rd = spix->DR; \
	}
#define is_spi_busy(spix) (spix->SR & SPI_SR_BSY)
#define spi_send(spix, dat) spix->DR = dat
#define is_spi_tx_full(spix) ((spix->SR & SPI_SR_TXE) == 0)
#define is_spi_tx_empty(spix) (spix->SR & SPI_SR_TXE)
#define spi_read(spix) spix->DR

/*****************************************************************************
* @brief   spi data read.
*****************************************************************************/
uint8_t nor_spi_rb(void)
{
	spi_rx_reset(NOR_SPI);

	//send data
	spi_send(NOR_SPI, 0xFF);
	spi_read_delay();

	//wait for trans complete
	while (is_spi_busy(NOR_SPI));

	while (!is_spi_rx_ready(NOR_SPI));

	//read data
	return (spi_read(NOR_SPI));
}

void nor_spi_wb(uint8_t dataW)
{
	volatile uint8_t rb;
	
	spi_rx_reset(NOR_SPI);

	//send data
	spi_send(NOR_SPI, dataW);
	spi_read_delay();

	//wait for trans complete
	while (is_spi_busy(NOR_SPI));

	while (!is_spi_rx_ready(NOR_SPI));

	//read data
	rb = spi_read(NOR_SPI);
}

/*****************************************************************************
* @brief   spi data write.
*****************************************************************************/
uint8_t nor_spi_cmd_send(const uint8_t *dataw, uint8_t Len)
{
	while (Len--)
	{
		//send data
		spi_send(NOR_SPI, *dataw++);

		spi_read_delay();

		while (is_spi_tx_full(NOR_SPI))
		{
		}
	}

	spi_read_delay();

	//wait for trans complete
	while (is_spi_busy(NOR_SPI) || !is_spi_tx_empty(NOR_SPI))
	{
	}

	spi_rx_reset(NOR_SPI);

	return (0);
}

uint8_t nor_qpi_cmd_send(const uint8_t *dataw, uint8_t Len)
{
	return nor_spi_cmd_send(dataw, Len);
}

uint8_t nor_spi_cmd_read(uint8_t *datar, uint8_t Len)
{
	uint32_t rcnt = 0;

	spi_rx_reset(NOR_SPI);

	while (Len--)
	{
		//send data
		spi_send(NOR_SPI, 0xFF);

		spi_read_delay();

		while (!is_spi_rx_ready(NOR_SPI))
		{
		}

		datar[rcnt++] = spi_read(NOR_SPI);
	}

	return 0;
}

uint8_t nor_qpi_cmd_read(uint8_t *datar, uint8_t Len)
{
	return nor_spi_cmd_read(datar, Len);
}

/*****************************************************************************
* @brief   spi data write.
*****************************************************************************/
uint8_t nor_spi_write(const uint8_t *dataw, uint32_t Len)
{
	while (Len--)
	{
		//send data
		spi_send(NOR_SPI, *dataw++);

		spi_read_delay();

		while (is_spi_tx_full(NOR_SPI))
		{
		}
	}

	spi_read_delay();

	//wait for trans complete
	while (is_spi_busy(NOR_SPI) || !is_spi_tx_empty(NOR_SPI))
	{
	}

	spi_rx_reset(NOR_SPI);

	return (0);
}

/*****************************************************************************
* @brief   spi data read.
*****************************************************************************/
uint8_t nor_spi_read(uint8_t *datar, uint32_t Len)
{
	uint32_t rcnt = 0;

	spi_rx_reset(NOR_SPI);

	while (Len--)
	{
		//send data
		spi_send(NOR_SPI, 0xFF);

		spi_read_delay();

		while (!is_spi_rx_ready(NOR_SPI))
		{
		}

		datar[rcnt++] = spi_read(NOR_SPI);
	}

	return 0;
}

/*****************************************************************************
* @brief   qpi data write.
*****************************************************************************/
uint8_t nor_qpi_write(const uint8_t *dataw, uint32_t Len)
{
	nor_spi_write(dataw, Len);
	return (0);
}

/*****************************************************************************
* @brief   qpi data read.
*****************************************************************************/
uint8_t nor_qpi_read(uint8_t *datar, uint32_t Len)
{
	nor_spi_read(datar, Len);

	return (0);
}
